import * as fs from 'fs'
import * as path from 'path'
import { TextDocument, window, Position } from 'vscode'
import { quickParseStyle } from './quickParseStle'
import { Config } from './config'
import { getRoot } from './helper'
import loadScss from './loadScss'
import loadLess from './loadLess'

export interface Style {
  name: string
  pos: Position
  doc: string
}

export interface StyleFile {
  file: string
  styles: Style[]
}

const fileCache: { [file: string]: { mtime: Date; value: StyleFile } } = {}

function isScss(file: string): boolean {
  return /\.s[ac]ss/.test(file)
}

function isLess(file: string): boolean {
  return file.endsWith('.less');
}

async function getStyleContent(file: string, content: string) {
  if (isLess(file)) {
    return await loadLess(file, content);
  } else if (isScss(file)) {
    return await loadScss(file, content);
  } else {
    return content;
  }
}

export async function parseStyleFile(file: string) {
  try {
    let cache = fileCache[file]
    let editor = window.visibleTextEditors.find(e => e.document.fileName === file)
    if (editor) {
      let content = editor.document.getText()
      content = await getStyleContent(file, content)
      return { file, styles: quickParseStyle(content) }
    } else {
      const stat = fs.statSync(file)
      if (cache && stat.mtime <= cache.mtime) {
        return cache.value
      }

      let content = fs.readFileSync(file).toString();
      content = await getStyleContent(file, content);

      cache = {
        mtime: stat.mtime,
        value: {
          file,
          styles: quickParseStyle(content),
        },
      }
      fileCache[file] = cache
      return cache.value
    }
  } catch (e) {
    return {
      file,
      styles: [],
    }
  }
}

export async function getClass(doc: TextDocument, config: Config) {
  let locals = await getLocalClass(doc, config);
  let globals = await getGlobalClass(doc, config);
  return [...locals, ...globals];
}

export async function getLocalClass(doc: TextDocument, config: Config) {
  let exts = config.styleExtensions || []
  let dir = path.dirname(doc.fileName)
  let basename = path.basename(doc.fileName, path.extname(doc.fileName))
  let localFile = exts.map(e => path.join(dir, basename + '.' + e)).find(f => fs.existsSync(f))
  if (localFile) {
    return [await parseStyleFile(localFile)]
  }

  return []
}

export async function getGlobalClass(doc: TextDocument, config: Config) {
  let root = getRoot(doc) as string
  if (!root) return []
  let files = (config.globalStyleFiles || []).map(f => path.resolve(root, f))
  let styles = [];
  for (const file of files) {
    styles.push(await parseStyleFile(file))
  }

  return styles;
}
